/*============================================================
  * Thu vien LCD du dung giao tiep 4 day.
  * nguoi tao QuyenCV - copyright website: hocavr.com.
  * Su dung giao tiep giua VDK PIC voi LCD dung trong CCS.
=============================================================*/
#include <stdio.h>

#define      sbi(port,bit)      (port)|=(1<<(bit))
#define      cbi(port,bit)      (port)&=~(1<<(bit))

#define      EN      3
#define      RW      2
#define      RS      1

#define      CTRL            LATD
#define      DDR_CTRL      	TRISD

#define      DATA_O           LATD
#define      DATA_I           PORTD
#define      DDR_DATA         TRISD

unsigned char  Read2Nib();
void Write2Nib(char chr);
void wait_LCD();
void init_LCD();
void home_LCD();
void move_LCD(unsigned char  y,unsigned char  x);
void clr_LCD();
void putChar_LCD(char chr);
void print_LCD(rom char *str);
void print_fLCD(float a);      // hien thi so thu chinh xac 2 chu so.
void print_iLCD(int a); 		// hien thi interger.
void print_hex(unsigned int val);

unsigned char  Read2Nib(){
   unsigned char  HNib, LNib;
   DATA_O |=0xF0;
   
   sbi(CTRL,EN); //enable   
   DDR_DATA |=0xF0;      // 4 bit cao la input.   
   HNib=DATA_I & 0xF0;
   cbi(CTRL,EN); //disable
   
   sbi(CTRL,EN); //enable
   LNib = DATA_I & 0xF0;
   cbi(CTRL,EN); //disable
   LNib>>=4;
   return (HNib|LNib);
}

void Write2Nib(char chr){

   unsigned char  HNib, LNib, temp_data;   
   temp_data=DATA_O & 0x0F;

   HNib=chr & 0xF0;
   LNib=(chr<<4) & 0xF0;      
      
   DATA_O =(HNib |temp_data);   
   sbi(CTRL,EN); //enable
   cbi(CTRL,EN); //disable   
   
   DATA_O =(LNib|temp_data);      
   sbi(CTRL,EN); //enable
   cbi(CTRL,EN); //disable
}

void wait_LCD()
{
   unsigned char  temp_val=0;
      while(1){
         cbi(CTRL,RS); //RS=0 mean the following data is COMMAND (not normal DATA)
         sbi(CTRL,RW); //the Direction of this COMMAND is from LCD -> chip
         temp_val=Read2Nib();
         if (!(temp_val & (1<<7))) break;      // !(temp_val & (1<<7))
      }
      cbi(CTRL,RW); //ready for next step   
      DDR_DATA=0x00;//Ready to Out
}   

void init_LCD()
{
   DDR_DATA=0x00;
   DDR_CTRL=0x00;      // output.
   DATA_O = 0x00;
//Function set------------------------------------------------------------------------------
   cbi(CTRL,RS);   // the following data is COMMAND
   cbi(CTRL, RW); // PIC->LCD
   cbi(CTRL, EN);

   sbi(CTRL,EN); //enable
   sbi(DATA_O, 5); 
   cbi(CTRL,EN); //disable
   wait_LCD();      
   Write2Nib(0x28);//
   wait_LCD();   
   
   //Display control-------------------------------------------------------------------------      
   cbi(CTRL,RS); // the following data is COMMAND   
   Write2Nib(0x0E);
   wait_LCD();      

   //Entry mode set------------------------------------------------------------------------
   cbi(CTRL,RS); // the following data is COMMAND 
   Write2Nib(0x06);
   wait_LCD();
}

void home_LCD()
{
   cbi(CTRL,RS); // the following data is COMMAND 
   Write2Nib(0x02);
   wait_LCD();
}

void move_LCD(unsigned char  y,unsigned char  x)
{
   unsigned char  Ad;
   Ad=64*(y-1)+(x-1)+0x80; //
   cbi(CTRL,RS); // the following data is COMMAND

   Write2Nib(Ad);
   wait_LCD();

}

void clr_LCD()
{
   cbi(CTRL,RS); //RS=0 mean the following data is COMMAND (not normal DATA)
   Write2Nib(0x01);
   wait_LCD();   
      
}

void putChar_LCD(char chr)
{
   sbi(CTRL,RS); //this is a normal DATA   
   Write2Nib(chr);
   wait_LCD();   
}

void print_LCD(rom char *str)
{	
	    while( *str != 0 )
    	    putChar_LCD(*str++);

}

void print_hex(unsigned int val)
{
	unsigned char a;
	
	a = (val>>12)&0x0f;
	a = a + ((a>9) ? ('A' - 10):'0');
	putChar_LCD(a);	
	
	a = (val>>8)&0x0f;
	a = a + ((a>9) ? ('A' - 10):'0');
	putChar_LCD(a);	
	
	a = (val>>4)&0x0f;	
	a = a + ((a>9) ? ('A' - 10):'0');
	putChar_LCD(a);	
	
	a = (val&0x0f);
	a = a + ((a>9) ? ('A' - 10):'0');
	putChar_LCD(a);	
}

void print_fLCD(float a)
{
       unsigned char temp = 0,temp_a;	   
	   float save_a = a - (int) a;
	   while((int) a > 0){
			a /=10;
			temp++;
	   }
		
		if(temp == 0){
			putChar_LCD('0');
			putChar_LCD('.');
		}
		else {
			while(temp){
				a *=10;
				temp_a = ((int )a)%10;
				temp_a += '0';
				putChar_LCD(temp_a);			
				temp --;
			}
			putChar_LCD('.');
		}
		save_a *= 10;
		temp_a = ((int )save_a)%10;
		temp_a += '0';
		putChar_LCD(temp_a);
		save_a *= 10;
		temp_a = ((int )save_a)%10;
		temp_a += '0';
		putChar_LCD(temp_a);
    
}


void print_iLCD(int a)
{
	int temp = 1,save_a = a;
	char temp_a;	
	   while( save_a > 10){
			save_a /=10;
			temp *= 10;
	   }
		
		if(temp > 1){
			while(temp > 1){					
				temp_a = a/temp;
				a -= temp*temp_a;
				temp_a += '0';
				putChar_LCD(temp_a);			
				temp /= 10;
			}
		}
		putChar_LCD(a +'0');

}


